package com.ea.admin.service.impl;

import com.ea.admin.service.ChartGenerationService;
import com.ea.common.report.pojo.vo.NormVo;
import com.ea.common.report.pojo.vo.PointVo;
import com.ea.common.report.pojo.vo.ReportPropertiesVo;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import javax.imageio.ImageIO;

/**
 * 图表生成服务实现类
 * @author luxl
 * date:2025-06-20
 */
@Service
public class ChartGenerationServiceImpl implements ChartGenerationService {

    private static final Logger logger = LoggerFactory.getLogger(ChartGenerationServiceImpl.class);

    //-----------------------------个人情绪分布图--------------------------------------------------------

    /**
     * 生成个人情绪分布环状饼图
     */
    @Override
    public String generateEmotionDistributionChart(List<ReportPropertiesVo> items) {
        try {
            // 准备数据
            Map<String, ReportPropertiesVo> itemMap = new HashMap<>();
            for (ReportPropertiesVo item : items) {
                itemMap.put(item.getName(), item);
            }

            // 获取三个情绪数据
            ReportPropertiesVo physiological = itemMap.get("生理情绪");
            ReportPropertiesVo positive = itemMap.get("正面情绪");
            ReportPropertiesVo negative = itemMap.get("负面情绪");

            // 如果数据不完整，返回占位图
            if (physiological == null || positive == null || negative == null) {
                logger.warn("情绪分布数据不完整，使用占位图");
                return generateEmotionPlaceholderChart();
            }

            // 获取数值
            double physioValue = parseValue(physiological.getValue());
            double positiveValue = parseValue(positive.getValue());
            double negativeValue = parseValue(negative.getValue());

            // 生成环状饼图
            return generateEmotionRingChart(physioValue, positiveValue, negativeValue);

        } catch (Exception e) {
            logger.error("生成情绪分布图失败", e);
            return generateEmotionPlaceholderChart();
        }
    }

    /**
     * 解析数值
     */
    private double parseValue(String value) {
        try {
            return value != null ? Double.parseDouble(value) : 0.0;
        } catch (NumberFormatException e) {
            return 0.0;
        }
    }

    /**
     * 生成情绪环状饼图
     */
    private String generateEmotionRingChart(double physiological, double positive, double negative) {
        try {
            // 创建360x250的图片
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 计算总值和角度
            double total = physiological + positive + negative;
            if (total == 0) {
                return generateEmotionPlaceholderChart();
            }

            double physioAngle = (physiological / total) * 360;
            double positiveAngle = (positive / total) * 360;
            double negativeAngle = (negative / total) * 360;

            // 定义颜色
            Color blueColor = new Color(45, 165, 205);
            Color greenColor = new Color(182, 227, 182);
            Color purpleColor = new Color(143, 68, 143);

            // 绘制环状图
            int centerX = 180, centerY = 110;
            int outerRadius = 80, innerRadius = 35;

            // 绘制生理情绪扇形
            g2d.setColor(blueColor);
            drawRingSegment(g2d, centerX, centerY, outerRadius, innerRadius, 0, physioAngle);

            // 绘制正面情绪扇形
            g2d.setColor(greenColor);
            drawRingSegment(g2d, centerX, centerY, outerRadius, innerRadius, physioAngle, positiveAngle);

            // 绘制负面情绪扇形
            g2d.setColor(purpleColor);
            drawRingSegment(g2d, centerX, centerY, outerRadius, innerRadius, physioAngle + positiveAngle, negativeAngle);

            // 绘制百分比标签
            g2d.setColor(Color.white);
            g2d.setFont(new Font("SimSun", Font.BOLD, 16));

            // 生理情绪标签
            if (physioAngle > 10) {
                double labelAngle = Math.toRadians(physioAngle / 2);
                int labelX = centerX + (int) ((outerRadius + innerRadius) / 2 * Math.cos(labelAngle));
                int labelY = centerY + (int) ((outerRadius + innerRadius) / 2 * Math.sin(labelAngle));
                String percent = String.format("%.1f%%", (physiological / total) * 100);
                drawCenteredString(g2d, percent, labelX, labelY);
            }

            // 正面情绪标签
            if (positiveAngle > 10) {
                double labelAngle = Math.toRadians(physioAngle + positiveAngle / 2);
                int labelX = centerX + (int) ((outerRadius + innerRadius) / 2 * Math.cos(labelAngle));
                int labelY = centerY + (int) ((outerRadius + innerRadius) / 2 * Math.sin(labelAngle));
                String percent = String.format("%.1f%%", (positive / total) * 100);
                drawCenteredString(g2d, percent, labelX, labelY);
            }

            // 负面情绪标签
            if (negativeAngle > 10) {
                double labelAngle = Math.toRadians(physioAngle + positiveAngle + negativeAngle / 2);
                int labelX = centerX + (int) ((outerRadius + innerRadius) / 2 * Math.cos(labelAngle));
                int labelY = centerY + (int) ((outerRadius + innerRadius) / 2 * Math.sin(labelAngle));
                String percent = String.format("%.1f%%", (negative / total) * 100);
                drawCenteredString(g2d, percent, labelX, labelY);
            }

            // 绘制图例
            drawEmotionLegend(g2d, blueColor, greenColor, purpleColor, physiological, positive, negative, total);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成环状饼图失败", e);
            return generateEmotionPlaceholderChart();
        }
    }

    /**
     * 绘制环状扇形
     */
    private void drawRingSegment(Graphics2D g2d, int centerX, int centerY, int outerRadius, int innerRadius, double startAngle, double arcAngle) {
        if (arcAngle <= 0) {
            return;
        }

        // 创建环状路径
        java.awt.geom.Area outerCircle = new java.awt.geom.Area(new java.awt.geom.Ellipse2D.Double(
                centerX - outerRadius, centerY - outerRadius, outerRadius * 2, outerRadius * 2));
        java.awt.geom.Area innerCircle = new java.awt.geom.Area(new java.awt.geom.Ellipse2D.Double(
                centerX - innerRadius, centerY - innerRadius, innerRadius * 2, innerRadius * 2));

        outerCircle.subtract(innerCircle);

        // 创建扇形路径
        java.awt.geom.Arc2D.Double arc = new java.awt.geom.Arc2D.Double(
                centerX - outerRadius, centerY - outerRadius, outerRadius * 2, outerRadius * 2,
                -startAngle, -arcAngle, java.awt.geom.Arc2D.PIE);

        java.awt.geom.Area sector = new java.awt.geom.Area(arc);
        java.awt.geom.Area innerArc = new java.awt.geom.Area(new java.awt.geom.Ellipse2D.Double(
                centerX - innerRadius, centerY - innerRadius, innerRadius * 2, innerRadius * 2));
        sector.subtract(innerArc);

        g2d.fill(sector);
    }

    /**
     * 绘制居中文字
     */
    private void drawCenteredString(Graphics2D g2d, String text, int x, int y) {
        FontMetrics fm = g2d.getFontMetrics();
        int textX = x - fm.stringWidth(text) / 2;
        int textY = y + fm.getAscent() / 2;
        g2d.drawString(text, textX, textY);
    }

    /**
     * 绘制图例
     */
    private void drawEmotionLegend(Graphics2D g2d, Color blueColor, Color greenColor, Color purpleColor,
                                   double physiological, double positive, double negative, double total) {
        int legendY = 220;
        int legendX = 40;
        int legendSpacing = 100;

        g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));

        // 生理情绪图例
        g2d.setColor(blueColor);
        g2d.fillRect(legendX, legendY - 2, 12, 12);
        g2d.setColor(Color.BLACK);
        String physioText = "生理情绪";
        g2d.drawString(physioText, legendX + 16, legendY + 10);

        // 正面情绪图例
        g2d.setColor(greenColor);
        g2d.fillRect(legendX + legendSpacing, legendY - 2, 12, 12);
        g2d.setColor(Color.BLACK);
        String positiveText = "正面情绪";
        g2d.drawString(positiveText, legendX + legendSpacing + 16, legendY + 10);

        // 负面情绪图例
        g2d.setColor(purpleColor);
        g2d.fillRect(legendX + legendSpacing * 2, legendY - 2, 12, 12);
        g2d.setColor(Color.BLACK);
        String negativeText = "负面情绪";
        g2d.drawString(negativeText, legendX + legendSpacing * 2 + 16, legendY + 10);
    }


    //-----------------------------个人性格倾向图--------------------------------------------------------

    /**
     * 生成个人性格倾向环状图
     */
    @Override
    public String generatePersonalityChart(int extraversion, int stability) {
        try {
            // 根据外向性和稳定性计算性格类型
            String personalityType = calculatePersonalityType(extraversion, stability);

            // 创建图片
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 根据性格类型选择颜色
            Color personalityColor = getPersonalityColor(personalityType);

            // 环形图参数
            int centerX = 180, centerY = 110;
            int outerRadius = 80, innerRadius = 35;

            // 绘制完整的环形
            g2d.setColor(personalityColor);
            drawFullRing(g2d, centerX, centerY, outerRadius, innerRadius);

            // 绘制性格类型标签
            g2d.setColor(Color.WHITE);
            g2d.setFont(new Font("SimSun", Font.BOLD, 16));
            drawCenteredString(g2d, personalityType, centerX, centerY);


            // 绘制性格类型说明
            drawPersonalityDescription(g2d, personalityType, extraversion, stability);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成性格倾向图失败", e);
            return generatePersonalityPlaceholderChart();
        }
    }

    /**
     * 绘制完整的环形
     */
    private void drawFullRing(Graphics2D g2d, int centerX, int centerY, int outerRadius, int innerRadius) {
        // 创建环状路径
        java.awt.geom.Area outerCircle = new java.awt.geom.Area(new java.awt.geom.Ellipse2D.Double(
                centerX - outerRadius, centerY - outerRadius, outerRadius * 2, outerRadius * 2));
        java.awt.geom.Area innerCircle = new java.awt.geom.Area(new java.awt.geom.Ellipse2D.Double(
                centerX - innerRadius, centerY - innerRadius, innerRadius * 2, innerRadius * 2));

        outerCircle.subtract(innerCircle);
        g2d.fill(outerCircle);
    }

    /**
     * 绘制性格类型说明
     */
    private void drawPersonalityDescription(Graphics2D g2d, String personalityType, int extraversion, int stability) {
        int descY = 220;
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));

        // 显示性格类型
        String typeText = "性格类型：" + personalityType;
        FontMetrics fm = g2d.getFontMetrics();
        int typeX = (360 - fm.stringWidth(typeText)) / 2;
        g2d.drawString(typeText, typeX, descY);

        // 显示外向性和稳定性数值
        String scoreText = String.format("外向性：%d  稳定性：%d", extraversion, stability);
        int scoreX = (360 - fm.stringWidth(scoreText)) / 2;
        g2d.drawString(scoreText, scoreX, descY + 20);
    }

    /**
     * 根据性格类型获取对应颜色
     */
    private Color getPersonalityColor(String personalityType) {
        switch (personalityType) {
            case "平静型":
                return new Color(91, 188, 232);
            case "热情型":
                return new Color(128, 255, 213);
            case "敏感型":
                return new Color(134, 68, 134);
            case "兴奋型":
                return new Color(189, 177, 90);
            default:
                return new Color(169, 169, 169);
        }
    }

    //-----------------------------心理频谱图--------------------------------------------------------

    /**
     * 绘制心理频谱图
     */
    @Override
    public String generateSpectrumChart(List<PointVo> mentalSpectrum) {
        try {
            if (mentalSpectrum == null || mentalSpectrum.isEmpty()) {
                return generateSpectrumPlaceholderChart();
            }

            // 创建图片
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 定义绘图区域
            int chartX = 40;
            int chartY = 40;
            int chartWidth = 280;
            int chartHeight = 160;

            // 绘制坐标轴
            drawSpectrumAxes(g2d, chartX, chartY, chartWidth, chartHeight);

            // 绘制频谱数据
            drawSpectrumData(g2d, mentalSpectrum, chartX, chartY, chartWidth, chartHeight);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成心理频谱图失败", e);
            return generateSpectrumPlaceholderChart();
        }
    }

    /**
     * 绘制频谱图坐标轴
     */
    private void drawSpectrumAxes(Graphics2D g2d, int chartX, int chartY, int chartWidth, int chartHeight) {
        g2d.setColor(new Color(127, 178, 250));
        g2d.setStroke(new BasicStroke(2));
        // 绘制X轴
        g2d.drawLine(chartX, chartY + chartHeight, chartX + chartWidth, chartY + chartHeight);

        // 绘制X轴刻度和标签
        g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
        FontMetrics fm = g2d.getFontMetrics();

        double maxX = 5.04;
        double tickInterval = 0.28;

        for (double x = 0; x <= maxX; x += tickInterval) {
            int pixelX = chartX + (int) ((x / maxX) * chartWidth);

            // 绘制刻度线
            g2d.drawLine(pixelX, chartY + chartHeight, pixelX, chartY + chartHeight + 5);

            // 绘制纵向标签（旋转90度）
            String label = String.format("%.2f", x);

            // 保存当前变换
            AffineTransform originalTransform = g2d.getTransform();

            // 旋转90度，底部朝向图表
            g2d.translate(pixelX, chartY + chartHeight + 15);
            g2d.rotate(-Math.PI / 2);

            // 绘制标签
            g2d.setColor(Color.GRAY);
            g2d.drawString(label, -18, 5);
            g2d.setColor(new Color(127, 178, 250));
            // 恢复变换
            g2d.setTransform(originalTransform);
        }
    }

    /**
     * 绘制频谱数据
     */
    private void drawSpectrumData(Graphics2D g2d, List<PointVo> mentalSpectrum, int chartX, int chartY, int chartWidth, int chartHeight) {
        if (mentalSpectrum == null || mentalSpectrum.isEmpty()) {
            return;
        }

        // 找到Y轴的最大值用于缩放
        double maxY = mentalSpectrum.stream()
                .mapToDouble(PointVo::getY)
                .max()
                .orElse(1.0);

        if (maxY == 0) {
            maxY = 1.0;
        }

        // 设置竖线颜色为蓝色
        g2d.setColor(new Color(127, 178, 250));
        g2d.setStroke(new BasicStroke(4));

        double maxX = 5.04;

        // 绘制每个数据点的竖线
        for (PointVo point : mentalSpectrum) {
            if (point.getX() == null || point.getY() == null) {
                continue;
            }

            double x = point.getX();
            double y = point.getY();

            // 只绘制在X轴范围内的数据
            if (x >= 0 && x <= maxX && y > 0) {
                // 计算像素坐标
                int pixelX = chartX + (int) ((x / maxX) * chartWidth);
                int lineHeight = (int) ((y / maxY) * chartHeight);
                int startY = chartY + chartHeight;
                int endY = startY - lineHeight;

                // 绘制竖线
                g2d.drawLine(pixelX, startY, pixelX, endY);
            }
        }
    }

    //-----------------------------心理变化基础代谢图--------------------------------------------------------

    @Override
    public String generateMetabolismChart(List<PointVo> mentalRateData) {
        try {
            if (mentalRateData == null || mentalRateData.isEmpty()) {
                return generateMetabolismPlaceholderChart();
            }

            // 创建图片
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 定义绘图区域
            int chartX = 50;
            int chartY = 30;
            int chartWidth = 280;
            int chartHeight = 180;


            // 绘制坐标轴
            g2d.setColor(Color.BLACK);
            g2d.setStroke(new BasicStroke(1.5f));
            // X轴
            g2d.drawLine(chartX, chartY + chartHeight, chartX + chartWidth, chartY + chartHeight);
            // Y轴
            g2d.drawLine(chartX, chartY, chartX, chartY + chartHeight);

            // 绘制网格线
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.setStroke(new BasicStroke(0.5f));

            // X轴网格线和标签 (0-10，每隔2个单位)
            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
            for (int i = 0; i <= 5; i++) {
                int value = i * 2;
                int x = chartX + (int) (chartWidth * value / 10.0);

                // 绘制网格线
                if (i > 0) {
                    g2d.drawLine(x, chartY, x, chartY + chartHeight);
                }

                // 绘制X轴标签
                g2d.setColor(Color.BLACK);
                String label = String.valueOf(value);
                FontMetrics fm = g2d.getFontMetrics();
                g2d.drawString(label, x - fm.stringWidth(label) / 2, chartY + chartHeight + 15);
                g2d.setColor(Color.LIGHT_GRAY);
            }

            // Y轴网格线和标签 (0-100，每隔20)
            for (int i = 0; i <= 5; i++) {
                int value = i * 20;
                int y = chartY + chartHeight - (int) (chartHeight * value / 100.0);

                // 绘制网格线
                if (i > 0) {
                    g2d.drawLine(chartX, y, chartX + chartWidth, y);
                }

                // 绘制Y轴标签
                g2d.setColor(Color.BLACK);
                String label = String.valueOf(value);
                FontMetrics fm = g2d.getFontMetrics();
                g2d.drawString(label, chartX - fm.stringWidth(label) - 5, y + fm.getHeight() / 3);
                g2d.setColor(Color.LIGHT_GRAY);
            }

            // 绘制坐标轴单位标签
            g2d.setColor(Color.BLACK);
            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
            FontMetrics fm = g2d.getFontMetrics();

            // X轴单位
            String xUnit = "E (kcal/min)";
            g2d.drawString(xUnit, chartX + chartWidth - fm.stringWidth(xUnit), chartY + chartHeight + 30);

            // Y轴单位
            String yUnit = "I (%)";
            g2d.drawString(yUnit, chartX - 40, chartY + 20);

            // 过滤并排序数据点
            List<PointVo> validPoints = mentalRateData.stream()
                    .filter(point -> point.getX() != null && point.getY() != null &&
                            point.getX() >= 0 && point.getX() <= 10 &&
                            point.getY() >= 0 && point.getY() <= 100)
                    .sorted((p1, p2) -> Double.compare(p1.getX(), p2.getX()))
                    .collect(Collectors.toList());

            if (!validPoints.isEmpty()) {
                // 绘制连线
                g2d.setColor(new Color(127, 178, 250));
                g2d.setStroke(new BasicStroke(4.0f));

                for (int i = 0; i < validPoints.size() - 1; i++) {
                    PointVo current = validPoints.get(i);
                    PointVo next = validPoints.get(i + 1);

                    int x1 = chartX + (int) (chartWidth * current.getX() / 10.0);
                    int y1 = chartY + chartHeight - (int) (chartHeight * current.getY() / 100.0);
                    int x2 = chartX + (int) (chartWidth * next.getX() / 10.0);
                    int y2 = chartY + chartHeight - (int) (chartHeight * next.getY() / 100.0);

                    g2d.drawLine(x1, y1, x2, y2);
                }

                // 绘制数据点
                g2d.setColor(new Color(127, 178, 250));
                for (PointVo point : validPoints) {
                    int x = chartX + (int) (chartWidth * point.getX() / 10.0);
                    int y = chartY + chartHeight - (int) (chartHeight * point.getY() / 100.0);
                    g2d.fillOval(x - 3, y - 3, 5, 5);
                }
            }

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "PNG", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成心理变化基础代谢图失败", e);
            return generateMetabolismPlaceholderChart();
        }
    }

    //-----------------------------个人/群体心理常模对比图----------------------------------------------------

    /**
     * 生成个人/群体心理常模对比雷达图
     */
    @Override
    public String generateRadarChart(List<NormVo> Norm, boolean isPersonal) {
        try {
            if (Norm == null || Norm.isEmpty()) {
                return generateRadarPlaceholderChart();
            }

            // 排除心率、血压、血氧
            List<NormVo> validData = Norm.stream()
                    .filter(norm -> norm.getIndex() != null && norm.getIndex() <= 12)
                    .sorted((a, b) -> Integer.compare(a.getIndex(), b.getIndex()))
                    .collect(Collectors.toList());

            if (validData.isEmpty()) {
                return generateRadarPlaceholderChart();
            }

            // 创建与模板匹配的图片尺寸
            BufferedImage image = new BufferedImage(432, 300, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 432, 300);


            // 雷达图参数
            int centerX = 216;
            int centerY = 140;
            int maxRadius = 90;
            int dataCount = validData.size();

            // 计算最大值用于缩放
            int maxValue = validData.stream()
                    .mapToInt(norm -> Math.max(norm.getNormValue() != null ? norm.getNormValue() : 0,
                            norm.getNowValue() != null ? norm.getNowValue() : 0))
                    .max().orElse(100);

            // 确保最大值至少为100，便于显示
            maxValue = Math.max(maxValue, 120);

            // 绘制同心圆网格线
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.setStroke(new BasicStroke(0.8f));
            for (int i = 1; i <= 4; i++) {
                int radius = maxRadius * i / 4;
                g2d.drawOval(centerX - radius, centerY - radius, radius * 2, radius * 2);
            }

            // 绘制轴线和标签
            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
            FontMetrics fm = g2d.getFontMetrics();

            for (int i = 0; i < dataCount; i++) {
                double angle = 2 * Math.PI * i / dataCount - Math.PI / 2;
                int endX = centerX + (int) (maxRadius * Math.cos(angle));
                int endY = centerY + (int) (maxRadius * Math.sin(angle));

                // 绘制轴线
                g2d.setColor(Color.LIGHT_GRAY);
                g2d.drawLine(centerX, centerY, endX, endY);

                // 绘制标签
                g2d.setColor(Color.BLACK);
                String label = validData.get(i).getPropertiesName();
                if (label.length() > 4) {
                    label = label.substring(0, 4);
                }

                // 计算标签位置
                int labelX = centerX + (int) ((maxRadius + 28) * Math.cos(angle));
                int labelY = centerY + (int) ((maxRadius + 28) * Math.sin(angle));

                // 调整标签位置避免重叠
                labelX -= fm.stringWidth(label) / 2;
                labelY += fm.getHeight() / 3;

                // 确保标签不超出图片边界
                labelX = Math.max(2, Math.min(labelX, 440 - fm.stringWidth(label) - 2));
                labelY = Math.max(fm.getHeight(), Math.min(labelY, 300 - fm.getHeight()));

                g2d.drawString(label, labelX, labelY);
            }
            // 绘制常模值多边形（蓝色）
            g2d.setColor(new Color(0, 123, 255, 100));
            g2d.setStroke(new BasicStroke(1.5f));

            int[] normXPoints = new int[dataCount];
            int[] normYPoints = new int[dataCount];

            for (int i = 0; i < dataCount; i++) {
                double angle = 2 * Math.PI * i / dataCount - Math.PI / 2;
                int value = validData.get(i).getNormValue() != null ? validData.get(i).getNormValue() : 0;
                int radius = (int) (maxRadius * value / (double) maxValue);

                normXPoints[i] = centerX + (int) (radius * Math.cos(angle));
                normYPoints[i] = centerY + (int) (radius * Math.sin(angle));
            }

            // 填充常模值区域
            g2d.fillPolygon(normXPoints, normYPoints, dataCount);

            // 绘制常模值边框
            g2d.setColor(new Color(0, 123, 255));
            g2d.drawPolygon(normXPoints, normYPoints, dataCount);

            // 绘制当前值多边形（红色）
            g2d.setColor(new Color(255, 99, 132, 100));

            int[] nowXPoints = new int[dataCount];
            int[] nowYPoints = new int[dataCount];

            for (int i = 0; i < dataCount; i++) {
                double angle = 2 * Math.PI * i / dataCount - Math.PI / 2;
                int value = validData.get(i).getNowValue() != null ? validData.get(i).getNowValue() : 0;
                int radius = (int) (maxRadius * value / (double) maxValue);

                nowXPoints[i] = centerX + (int) (radius * Math.cos(angle));
                nowYPoints[i] = centerY + (int) (radius * Math.sin(angle));
            }

            // 填充当前值区域
            g2d.fillPolygon(nowXPoints, nowYPoints, dataCount);

            // 绘制当前值边框
            g2d.setColor(new Color(255, 99, 132));
            g2d.drawPolygon(nowXPoints, nowYPoints, dataCount);

            // 绘制数据点
            for (int i = 0; i < dataCount; i++) {
                // 常模值点
                g2d.setColor(new Color(0, 123, 255));
                g2d.fillOval(normXPoints[i] - 2, normYPoints[i] - 2, 4, 4);

                // 当前值点
                g2d.setColor(new Color(255, 99, 132));
                g2d.fillOval(nowXPoints[i] - 2, nowYPoints[i] - 2, 4, 4);
            }

            // 绘制图例
            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
            FontMetrics legendFm = g2d.getFontMetrics();
            if(isPersonal) {
                // 常模值图例
                g2d.setColor(new Color(0, 123, 255));
                g2d.fillRect(100, 280, 10, 10);
                g2d.setColor(Color.BLACK);
                g2d.drawString("个人常模值", 115, 290);

                // 当前值图例
                g2d.setColor(new Color(255, 99, 132));
                g2d.fillRect(220, 280, 10, 10);
                g2d.setColor(Color.BLACK);
                g2d.drawString("个人当前值", 235, 290);
            }else{
                // 常模值图例
                g2d.setColor(new Color(0, 123, 255));
                g2d.fillRect(100, 280, 10, 10);
                g2d.setColor(Color.BLACK);
                g2d.drawString("群体常模值", 115, 290);

                // 当前值图例
                g2d.setColor(new Color(255, 99, 132));
                g2d.fillRect(220, 280, 10, 10);
                g2d.setColor(Color.BLACK);
                g2d.drawString("个人常模值", 235, 290);
            }

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "PNG", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成心理常模对比图失败", e);
            return generateRadarPlaceholderChart();
        }
    }
    //

    /**
     * 计算性格类型
     */
    private String calculatePersonalityType(int extraversion, int stability) {
        if (extraversion >= 51 && extraversion <= 100 && stability >= 51 && stability <= 100) {
            return "平静型";
        } else if (extraversion >= 0 && extraversion <= 50 && stability >= 51 && stability <= 100) {
            return "热情型";
        } else if (extraversion >= 0 && extraversion <= 50 && stability >= 0 && stability <= 50) {
            return "敏感型";
        } else if (extraversion >= 51 && extraversion <= 100 && stability >= 0 && stability <= 50) {
            return "兴奋型";
        } else {
            return "未知类型";
        }
    }



    /**
     * 生成情绪分布占位图
     */
    private String generateEmotionPlaceholderChart() {
        try {
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 绘制占位环形
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.fillOval(110, 20, 140, 140);
            g2d.setColor(Color.WHITE);
            g2d.fillOval(150, 60, 60, 60);

            // 设置文字
            g2d.setColor(Color.BLACK);
            g2d.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
            String text = "个人情绪分布";
            FontMetrics fm = g2d.getFontMetrics();
            int x = (360 - fm.stringWidth(text)) / 2;
            g2d.drawString(text, x, 200);

            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
            String noDataText = "暂无数据";
            fm = g2d.getFontMetrics();
            x = (360 - fm.stringWidth(noDataText)) / 2;
            g2d.drawString(noDataText, x, 220);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成情绪分布占位图失败", e);
            return "";
        }
    }

    /**
     * 生成性格倾向占位图
     */
    private String generatePersonalityPlaceholderChart() {
        try {
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 绘制占位环形
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.fillOval(110, 20, 140, 140);
            g2d.setColor(Color.WHITE);
            g2d.fillOval(150, 60, 60, 60);

            // 设置文字
            g2d.setColor(Color.BLACK);
            g2d.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
            String text = "个人性格倾向";
            FontMetrics fm = g2d.getFontMetrics();
            int x = (360 - fm.stringWidth(text)) / 2;
            g2d.drawString(text, x, 200);

            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
            String noDataText = "暂无数据";
            fm = g2d.getFontMetrics();
            x = (360 - fm.stringWidth(noDataText)) / 2;
            g2d.drawString(noDataText, x, 220);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成性格倾向占位图失败", e);
            return "";
        }
    }

    /**
     * 生成心理频谱图占位图
     */
    private String generateSpectrumPlaceholderChart() {
        try {
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 绘制占位框架
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.setStroke(new BasicStroke(2));
            g2d.drawRect(40, 40, 280, 160);

            // 绘制X轴
            g2d.drawLine(40, 200, 320, 200);

            // 绘制一些示例竖线
            g2d.setStroke(new BasicStroke(1));
            for (int i = 0; i < 10; i++) {
                int x = 60 + i * 25;
                int height = 20 + (int) (Math.random() * 80);
                g2d.drawLine(x, 200, x, 200 - height);
            }

            // 设置文字
            g2d.setColor(Color.BLACK);
            g2d.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
            String text = "心理频谱图";
            FontMetrics fm = g2d.getFontMetrics();
            int x = (360 - fm.stringWidth(text)) / 2;
            g2d.drawString(text, x, 25);

            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
            String noDataText = "暂无数据";
            fm = g2d.getFontMetrics();
            x = (360 - fm.stringWidth(noDataText)) / 2;
            g2d.drawString(noDataText, x, 230);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成心理频谱图占位图失败", e);
            return "";
        }
    }

    /**
     * 生成心理变化基础代谢图占位图
     */
    private String generateMetabolismPlaceholderChart() {
        try {
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 绘制占位框架
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.setStroke(new BasicStroke(2));
            g2d.drawRect(50, 30, 280, 180);

            // 绘制标题
            g2d.setColor(Color.BLACK);
            g2d.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
            FontMetrics titleFm = g2d.getFontMetrics();
            String title = "心理变化基础代谢图";
            int titleX = (360 - titleFm.stringWidth(title)) / 2;
            g2d.drawString(title, titleX, 20);

            // 绘制坐标轴
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.setStroke(new BasicStroke(1));
            g2d.drawLine(50, 210, 330, 210);
            g2d.drawLine(50, 30, 50, 210);

            // 绘制"暂无数据"文字
            g2d.setColor(Color.GRAY);
            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
            FontMetrics fm = g2d.getFontMetrics();
            String noDataText = "暂无数据";
            int textX = (360 - fm.stringWidth(noDataText)) / 2;
            int textY = 125;
            g2d.drawString(noDataText, textX, textY);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "PNG", baos);
            return Base64.encodeBase64String( baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成心理变化基础代谢图占位图失败", e);
            return null;
        }
    }

    /**
     * 生成个人/群体心理常模对比图占位图
     */
    private String generateRadarPlaceholderChart() {
        try {
            BufferedImage image = new BufferedImage(360, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            // 设置背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, 360, 250);

            // 绘制标题
            g2d.setColor(Color.BLACK);
            g2d.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
            FontMetrics titleFm = g2d.getFontMetrics();
            String title = "个人心理常模对比图";
            int titleX = (360 - titleFm.stringWidth(title)) / 2;
            g2d.drawString(title, titleX, 20);

            // 绘制占位雷达图框架
            int centerX = 180;
            int centerY = 135;
            int maxRadius = 80;

            g2d.setColor(Color.LIGHT_GRAY);
            g2d.setStroke(new BasicStroke(1));

            // 绘制同心圆
            for (int i = 1; i <= 4; i++) {
                int radius = maxRadius * i / 4;
                g2d.drawOval(centerX - radius, centerY - radius, radius * 2, radius * 2);
            }

            // 绘制轴线
            for (int i = 0; i < 12; i++) {
                double angle = 2 * Math.PI * i / 12 - Math.PI / 2;
                int endX = centerX + (int) (maxRadius * Math.cos(angle));
                int endY = centerY + (int) (maxRadius * Math.sin(angle));
                g2d.drawLine(centerX, centerY, endX, endY);
            }

            // 绘制"暂无数据"文字
            g2d.setColor(Color.GRAY);
            g2d.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
            FontMetrics fm = g2d.getFontMetrics();
            String noDataText = "暂无数据";
            int textX = (360 - fm.stringWidth(noDataText)) / 2;
            int textY = 135;
            g2d.drawString(noDataText, textX, textY);

            g2d.dispose();

            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "PNG", baos);
            return Base64.encodeBase64String(baos.toByteArray());

        } catch (Exception e) {
            logger.error("生成个人心理常模对比图占位图失败", e);
            return null;
        }
    }
}